﻿using Sage.DownloadLite.Enums;
using Sage.DownloadLite.Interfaces;
using Sage.DownloadLite.Models;

namespace Sage.DownloadLite.Core
{
    /// <summary>
    /// 下载管理器
    /// </summary>
    public sealed class DownloadManager
    {
        private readonly DownloadConfiguration _configuration;
        private readonly IHttpService _httpService;
        private static int _taskIdCounter = 0;

        // 单任务回调 - 修改为使用进度类
        private Action<SingleDownloadProgress>? _onProgress;
        private Func<TaskInfo, Exception, bool>? _onError;
        private Func<TaskInfo, string, FileExistsAction>? _onFileConflict;

        // 批量任务回调 - 修改为使用进度类
        private Action<BatchDownloadProgress>? _onBatchProgress;
        private Func<TaskInfo, Exception, bool>? _onBatchError;
        private Action<TaskInfo, FileInfo>? _onTaskCompleted;

        /// <summary>
        /// 私有构造函数
        /// </summary>
        /// <param name="configuration">配置</param>
        /// <param name="httpService">HTTP服务</param>
        private DownloadManager(DownloadConfiguration configuration, IHttpService httpService)
        {
            _configuration = configuration;
            _httpService = httpService;
            _configuration.ValidateAndCorrect();
            _httpService.SetTimeout(_configuration.Timeout);
            _httpService.SetUserAgent(_configuration.UserAgent);
        }

        /// <summary>
        /// 创建下载管理器实例
        /// </summary>
        /// <returns>下载管理器实例</returns>
        public static DownloadManager Create()
        {
            var configuration = new DownloadConfiguration();
            var httpService = HttpService.Instance;
            DebugLogger.WriteMessage("DownloadManager", "DownloadManager created");
            return new DownloadManager(configuration, httpService);
        }

        #region 链式配置方法

        /// <summary>
        /// 设置调试输出开关
        /// </summary>
        /// <param name="enabled">是否启用调试输出</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager Debug(bool enabled)
        {
            DebugLogger.Enabled = enabled;
            if (enabled)
            {
                DebugLogger.WriteMessage("DownloadManager", "Debug output enabled");
            }
            return this;
        }

        /// <summary>
        /// 设置用户代理字符串
        /// </summary>
        /// <param name="userAgent">用户代理字符串</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager UserAgent(string userAgent)
        {
            if (!string.IsNullOrWhiteSpace(userAgent))
            {
                _configuration.UserAgent = userAgent;
                _configuration.ValidateAndCorrect();
                _httpService.SetUserAgent(_configuration.UserAgent);
                DebugLogger.WriteMessage("DownloadManager", $"User agent set to {_configuration.UserAgent}");
            }
            return this;
        }

        /// <summary>
        /// 设置并发数量限制
        /// </summary>
        /// <param name="limit">并发数量</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager ConcurrentLimit(int limit)
        {
            _configuration.ConcurrentLimit = limit;
            _configuration.ValidateAndCorrect();
            DebugLogger.WriteMessage("DownloadManager", $"Concurrent limit set to {_configuration.ConcurrentLimit}");
            return this;
        }

        /// <summary>
        /// 设置超时时间
        /// </summary>
        /// <param name="timeout">超时时间</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager Timeout(TimeSpan timeout)
        {
            _configuration.Timeout = timeout;
            _configuration.ValidateAndCorrect();
            _httpService.SetTimeout(_configuration.Timeout);
            DebugLogger.WriteMessage("DownloadManager", $"Timeout set to {_configuration.Timeout}");
            return this;
        }

        /// <summary>
        /// 设置进度更新间隔
        /// </summary>
        /// <param name="interval">间隔百分比</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager ProgressInterval(double interval)
        {
            _configuration.ProgressInterval = interval;
            _configuration.ValidateAndCorrect();
            DebugLogger.WriteMessage("DownloadManager", $"Progress interval set to {_configuration.ProgressInterval}%");
            return this;
        }

        #endregion

        #region 回调设置方法

        /// <summary>
        /// 设置单任务进度回调
        /// </summary>
        /// <param name="callback">进度回调</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager OnProgress(Action<SingleDownloadProgress> callback)
        {
            _onProgress = callback;
            return this;
        }

        /// <summary>
        /// 设置单任务错误回调
        /// </summary>
        /// <param name="callback">错误回调</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager OnError(Func<TaskInfo, Exception, bool> callback)
        {
            _onError = callback;
            return this;
        }

        /// <summary>
        /// 设置文件冲突回调
        /// </summary>
        /// <param name="callback">文件冲突回调</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager OnFileConflict(Func<TaskInfo, string, FileExistsAction> callback)
        {
            _onFileConflict = callback;
            return this;
        }

        /// <summary>
        /// 设置批量任务进度回调
        /// </summary>
        /// <param name="callback">批量进度回调</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager OnBatchProgress(Action<BatchDownloadProgress> callback)
        {
            _onBatchProgress = callback;
            return this;
        }

        /// <summary>
        /// 设置批量任务错误回调
        /// </summary>
        /// <param name="callback">批量错误回调</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager OnBatchError(Func<TaskInfo, Exception, bool> callback)
        {
            _onBatchError = callback;
            return this;
        }

        /// <summary>
        /// 设置任务完成回调
        /// </summary>
        /// <param name="callback">任务完成回调</param>
        /// <returns>下载管理器实例</returns>
        public DownloadManager OnTaskCompleted(Action<TaskInfo, FileInfo> callback)
        {
            _onTaskCompleted = callback;
            return this;
        }

        #endregion

        #region 任务创建方法

        /// <summary>
        /// 创建任务信息
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="filePath">文件路径</param>
        /// <returns>任务信息</returns>
        public static TaskInfo CreateTaskInfo(string url, string filePath)
        {
            var id = Interlocked.Increment(ref _taskIdCounter);
            return new TaskInfo(id, url, filePath);
        }

        /// <summary>
        /// 创建任务信息
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="userData">用户自定义数据</param>
        /// <returns>任务信息</returns>
        public static TaskInfo CreateTaskInfo(string url, string filePath, object? userData)
        {
            var id = Interlocked.Increment(ref _taskIdCounter);
            return new TaskInfo(id, url, filePath)
            {
                UserData = userData
            };
        }

        #endregion

        #region 单任务下载方法

        /// <summary>
        /// 异步下载单个文件
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="filePath">保存文件路径</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>任务结果</returns>
        public async Task<TaskResult> DownloadSingleAsync(string url, string filePath, CancellationToken cancellationToken = default)
        {
            var taskInfo = CreateTaskInfo(url, filePath);
            return await DownloadSingleAsync(taskInfo, cancellationToken).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步下载单个文件
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="filePath">保存文件路径</param>
        /// <param name="userData">用户自定义数据</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>任务结果</returns>
        public async Task<TaskResult> DownloadSingleAsync(string url, string filePath, object? userData, CancellationToken cancellationToken = default)
        {
            var taskInfo = CreateTaskInfo(url, filePath, userData);
            return await DownloadSingleAsync(taskInfo, cancellationToken).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步下载单个文件
        /// </summary>
        /// <param name="taskInfo">任务信息</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>任务结果</returns>
        public async Task<TaskResult> DownloadSingleAsync(TaskInfo taskInfo, CancellationToken cancellationToken = default)
        {
            try
            {
                DebugLogger.WriteMessage("DownloadManager", $"Starting single download: Task {taskInfo.Id}");
                DebugLogger.WriteMessage("DownloadManager", $"Current ProgressInterval: {_configuration.ProgressInterval}%");

                // 处理文件冲突
                if (!await HandleFileConflictAsync(taskInfo, cancellationToken).ConfigureAwait(false))
                {
                    return new TaskResult
                    {
                        TaskInfo = taskInfo,
                        Success = false,
                        Status = DownloadLite.Enums.TaskStatus.Cancelled,
                        Error = new OperationCanceledException("File conflict resolved as skip"),
                        StartTime = DateTime.Now,
                        EndTime = DateTime.Now
                    };
                }

                // 创建进度回调 - 简化处理，传递给HttpService
                IProgress<SingleDownloadProgress>? progress = null;
                if (_onProgress != null)
                {
                    progress = new Progress<SingleDownloadProgress>(_onProgress);
                }

                var result = await _httpService.DownloadFileAsync(taskInfo, progress, _configuration.ProgressInterval, cancellationToken).ConfigureAwait(false);

                // 处理错误回调
                if (!result.Success && result.Error != null && _onError != null)
                {
                    var shouldContinue = _onError(taskInfo, result.Error);
                    DebugLogger.WriteMessage("DownloadManager", $"Error callback returned: {shouldContinue}");
                }

                DebugLogger.WriteMessage("DownloadManager", $"Single download completed: Task {taskInfo.Id}, Success: {result.Success}");
                return result;
            }
            catch (Exception ex)
            {
                DebugLogger.WriteMessage("DownloadManager", $"Single download exception: Task {taskInfo.Id}, Error: {ex.Message}");
                return new TaskResult
                {
                    TaskInfo = taskInfo,
                    Success = false,
                    Status = DownloadLite.Enums.TaskStatus.Failed,
                    Error = ex,
                    StartTime = DateTime.Now,
                    EndTime = DateTime.Now
                };
            }
        }

        /// <summary>
        /// 同步下载单个文件
        /// </summary>
        /// <param name="url">下载URL</param>
        /// <param name="filePath">保存文件路径</param>
        /// <returns>任务结果</returns>
        public TaskResult DownloadSingle(string url, string filePath)
        {
            var taskInfo = CreateTaskInfo(url, filePath);
            return DownloadSingle(taskInfo);
        }

        /// <summary>
        /// 同步下载单个文件
        /// </summary>
        /// <param name="taskInfo">任务信息</param>
        /// <returns>任务结果</returns>
        public TaskResult DownloadSingle(TaskInfo taskInfo)
        {
            if (SynchronizationContext.Current != null)
            {
                return Task.Run(async () => await DownloadSingleAsync(taskInfo).ConfigureAwait(false))
                          .GetAwaiter()
                          .GetResult();
            }
            else
            {
                return DownloadSingleAsync(taskInfo).GetAwaiter().GetResult();
            }
        }

        #endregion

        #region 批量下载方法

        /// <summary>
        /// 异步批量下载文件
        /// </summary>
        /// <param name="tasks">任务列表</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>批量下载结果</returns>
        public async Task<BatchDownloadResult> DownloadBatchAsync(IEnumerable<TaskInfo> tasks, CancellationToken cancellationToken = default)
        {
            var taskList = tasks.ToList();
            var result = new BatchDownloadResult
            {
                StartTime = DateTime.Now
            };

            try
            {
                DebugLogger.WriteMessage("DownloadManager", $"Starting batch download: {taskList.Count} tasks, Concurrent limit: {_configuration.ConcurrentLimit}");

                using var semaphore = new SemaphoreSlim(_configuration.ConcurrentLimit, _configuration.ConcurrentLimit);
                using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

                var completedCount = 0;
                var successfulCount = 0;
                var failedCount = 0;
                var totalCount = taskList.Count;

                var downloadTasks = taskList.Select(async taskInfo =>
                {
                    await semaphore.WaitAsync(linkedCts.Token).ConfigureAwait(false);
                    try
                    {
                        // 处理文件冲突
                        if (!await HandleFileConflictAsync(taskInfo, linkedCts.Token).ConfigureAwait(false))
                        {
                            var cancelledResult = new TaskResult
                            {
                                TaskInfo = taskInfo,
                                Success = false,
                                Status = DownloadLite.Enums.TaskStatus.Cancelled,
                                Error = new OperationCanceledException("File conflict resolved as skip"),
                                StartTime = DateTime.Now,
                                EndTime = DateTime.Now
                            };

                            lock (result)
                            {
                                result.CancelledTasks.Add(cancelledResult);
                            }
                            return;
                        }

                        var taskResult = await _httpService.DownloadFileAsync(taskInfo, null, _configuration.ProgressInterval, linkedCts.Token).ConfigureAwait(false);

                        lock (result)
                        {
                            result.CompletedTasks.Add(taskResult);
                            completedCount++;

                            if (taskResult.Success)
                                successfulCount++;
                            else
                                failedCount++;

                            // 触发批量进度回调 - 使用新的进度类
                            var percentage = (double)completedCount / totalCount * 100;
                            var batchProgress = new BatchDownloadProgress
                            {
                                CompletedTasks = completedCount,
                                TotalTasks = totalCount,
                                Percentage = percentage,
                                CurrentTask = taskInfo,
                                SuccessfulTasks = successfulCount,
                                FailedTasks = failedCount
                            };
                            _onBatchProgress?.Invoke(batchProgress);

                            // 触发任务完成回调
                            if (taskResult.Success && !string.IsNullOrEmpty(taskResult.FilePath))
                            {
                                var fileInfo = new FileInfo(taskResult.FilePath);
                                _onTaskCompleted?.Invoke(taskInfo, fileInfo);
                            }
                        }

                        // 处理批量错误回调
                        if (!taskResult.Success && taskResult.Error != null && _onBatchError != null)
                        {
                            var shouldContinue = _onBatchError(taskInfo, taskResult.Error);
                            if (!shouldContinue)
                            {
                                DebugLogger.WriteMessage("DownloadManager", $"Batch error callback requested cancellation for task {taskInfo.Id}");
                                linkedCts.Cancel();
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        var cancelledResult = new TaskResult
                        {
                            TaskInfo = taskInfo,
                            Success = false,
                            Status = DownloadLite.Enums.TaskStatus.Cancelled,
                            Error = new OperationCanceledException($"Task {taskInfo.Id} was cancelled"),
                            StartTime = DateTime.Now,
                            EndTime = DateTime.Now
                        };

                        lock (result)
                        {
                            result.CancelledTasks.Add(cancelledResult);
                        }
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                }).ToArray();

                await Task.WhenAll(downloadTasks).ConfigureAwait(false);

                result.Success = result.CompletedTasks.All(t => t.Success) && result.CancelledTasks.Count == 0;
                result.EndTime = DateTime.Now;
                result.TotalTime = result.EndTime - result.StartTime;

                DebugLogger.WriteMessage("DownloadManager", $"Batch download completed: Success: {result.SuccessfulTasks}, Failed: {result.FailedTasks}, Cancelled: {result.CancelledTasksCount}");
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.ErrorMessage = ex.Message;
                result.EndTime = DateTime.Now;
                result.TotalTime = result.EndTime - result.StartTime;
                DebugLogger.WriteMessage("DownloadManager", $"Batch download exception: {ex.Message}");
            }

            return result;
        }

        /// <summary>
        /// 同步批量下载文件
        /// </summary>
        /// <param name="tasks">任务列表</param>
        /// <returns>批量下载结果</returns>
        public BatchDownloadResult DownloadBatch(IEnumerable<TaskInfo> tasks)
        {
            if (SynchronizationContext.Current != null)
            {
                return Task.Run(async () => await DownloadBatchAsync(tasks).ConfigureAwait(false))
                          .GetAwaiter()
                          .GetResult();
            }
            else
            {
                return DownloadBatchAsync(tasks).GetAwaiter().GetResult();
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 处理文件冲突
        /// </summary>
        /// <param name="taskInfo">任务信息</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>是否继续下载</returns>
        private async Task<bool> HandleFileConflictAsync(TaskInfo taskInfo, CancellationToken cancellationToken)
        {
            if (!_httpService.FileExists(taskInfo.FilePath))
                return true;

            if (_onFileConflict == null)
            {
                DebugLogger.WriteMessage("DownloadManager", $"File exists but no conflict handler, overwriting: {taskInfo.FilePath}");
                return true;
            }

            return await Task.Run(() =>
            {
                var action = _onFileConflict(taskInfo, taskInfo.FilePath);
                DebugLogger.WriteMessage("DownloadManager", $"File conflict resolved as {action} for: {taskInfo.FilePath}");
                return action == FileExistsAction.Overwrite;
            }, cancellationToken).ConfigureAwait(false);
        }

        #endregion
    }
}